package org.byacko.simplemock;

public class ExpectBinder<T> extends ResultBinder<T> {

	private Object assertObject;
	private String assertMethod;

	public ExpectBinder(MockCreater<T> mockCreater, String methodName) {
		super(mockCreater, methodName);
	}

	/**
	 * アサーションを行うオブジェクトとメソッドを設定する。
	 * 
	 * @param assertObject
	 * @param assertMethod
	 * @return
	 */
	public ResultBinder<T> asserts(Object assertObject, String assertMethod) {
		assertAssertParams(assertObject, assertMethod);
		this.assertObject = assertObject;
		this.assertMethod = assertMethod;
		return this;
	}

	/**
	 * アサーションを行うメソッドを設定する。このメソッドを利用する場合、
	 * MockCreater#setAssertObjectを呼び出して共通のアサーションオブジェクトを設定する必要がある。
	 * 
	 * @param assertMethod
	 * @return
	 */
	public ResultBinder<T> asserts(String assertMethod) {
		return asserts(mockCreater.getAssertObject(), assertMethod);
	}

	/**
	 * モックの引数型を設定する。０個以上の引数の型
	 * 
	 * @param argTypes
	 * @return
	 */
	public ExpectBinder<T> with(Class<?>... argTypes) {
		this.argTypes = argTypes;
		return this;
	}

	@Override
	protected MethodHook prepareHook() {
		return new ExpectMethodHook(methodName, argTypes, newAsserter());
	}

	private Asserter newAsserter() {
		if (assertObject != null && assertMethod != null) {
			return new Asserter(assertObject, assertMethod, argTypes);
		} else {
			return null;
		}
	}
	
	private void assertAssertParams(Object assertObject, String assertMethod) {
		if(assertMethod == null) {
			throw new IllegalArgumentException("assertMethodはnullであってはなりません。");
		}
		if(assertObject == null) {
			throw new IllegalArgumentException("assertObjectはnullであってはなりません。");
		}
	}
}
